package com.jd.ymcc.service.impl;





import com.jd.ymcc.constants.CommonConstants;
import com.jd.ymcc.constants.SmsCodeConstants;
import com.jd.ymcc.domain.MessageSms;
import com.jd.ymcc.dto.RedisRegisterDto;
import com.jd.ymcc.enums.GlobalErrorCode;
import com.jd.ymcc.exception.GlobalCustomException;
import com.jd.ymcc.mapper.MessageSmsMapper;
import com.jd.ymcc.service.IVerifyCodeService;
import com.jd.ymcc.until.AssertUtil;
import com.jd.ymcc.until.StrUtils;
import com.jd.ymcc.until.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private MessageSmsMapper messageSmsMapper;
    @Autowired
    private SmsCodeConstants smsCodeConstants;

    @Override
    public String image(String key) {
        // 使用strutil工具类生成验证码
        String code = StrUtils.getComplexRandomString(4);
        // 保存到redis中
        redisTemplate.opsForValue().set(key,code,3, TimeUnit.MINUTES);
        // 使用工具类生成验证码图形的base64的字符串
        String base64Str = VerifyCodeUtils.verifyCode(110, 40, code);
        return base64Str;

    }

    @Override
    public void smsVerifyCode(String mobile) {
        // 1.参数为空&电话号码格式校验，使用断言工具进行判断，还需要进行黑名单校验
        AssertUtil.isPhone(mobile, GlobalErrorCode.NULL);

        // 2.根据电话号码拼接业务键，从Redis中获取验证码
        String key = String.format(CommonConstants.Register_PHONE_PREFIX, mobile);
        Object o = redisTemplate.opsForValue().get(key);
        // 2.1.存在
        String code = "";
        Long nowTime = System.currentTimeMillis();
        if (o != null){
            // 1.转换对象
            RedisRegisterDto redisRegisterDto = (RedisRegisterDto) o;
            // 2.1.1.判断是否超过1分钟，如果没超过抛出异常
            if ((nowTime - redisRegisterDto.getTime()) < smsCodeConstants.getInterval() ){
                throw new GlobalCustomException(GlobalErrorCode.OPERATING_FREQUENTLY_ERROR);
            }
            // 2.1.1.判断是否超过1分钟，如果超过一分钟，那么继续使用当前验证码
            code = redisRegisterDto.getCode();
        }else { // 2.2.不存在，生成新的验证码
            code = StrUtils.getRandomString(smsCodeConstants.getCodesize());
        }
        // 3.存入Redis中
        RedisRegisterDto redisRegisterDto = new RedisRegisterDto(code, nowTime);
        redisTemplate.opsForValue().set(key, redisRegisterDto, smsCodeConstants.getTimeout(), TimeUnit.MILLISECONDS);
        // 4.发送短信验证码
        sendMessageSms(code);
    }

    /*
     * @Description: 发送短信验证码
     * @Author: Director
     * @Date: 2022/8/14 15:48
     * @param code:
     * @return: void
     **/
    private void sendMessageSms(String code) {
        // 4.发送验证码，这里用日志打印代替，真实企业开发需要发送短信
        String content = String.format(smsCodeConstants.getSmsmessage(), code);
        log.info(content);
        // 5.保存短信消息记录
        // 5.1.获取request对象，可以封装为工具类  @TODO
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        // 5.2.初始化短信消息对象
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(smsCodeConstants.getSmstitle());
        messageSms.setSendTime(new Date());
        // 占位符替换为验证码
        messageSms.setContent(content);
        messageSms.setIp(request.getRemoteAddr());
        // 5.3.保存短信信息对象
        messageSmsMapper.insert(messageSms);
    }


/*    @Override
    public void smsCode(SmsImgDto smsImgDto) {

        //1.校验手机号是否为空
        if (smsImgDto.getMobile()==null){
            //错误抛异常
            throw new GlobalCustomException(GlobalErrorCode.PHONE_ERROR);
        }
        //2.校验图形验证码是否正确
        //3.查询redis是否有手机验证码
        String rediskey = "register:"+smsImgDto.getMobile();
        System.out.println(rediskey);
        // 保存到redis中
        Object obj = redisTemplate.opsForValue().get(rediskey);
        Date date = new Date();
        String code = "";
        //4.判断手机验证码是否为空
        if (obj!=null){
            //1.手机验证码存在
            String[] split = obj.toString().split(":");
            Long time = Long.valueOf(split[1]);
            //2.在判断时间是否大于1分钟
            if (date.getTime()-time<60000){
                throw new GlobalCustomException(GlobalErrorCode.OPERATING_FREQUENTLY_ERROR);
            }
            //大于一分钟，重新获取之前存在的验证码
            code = split[0];
        }else{ // 如果不存在创建一个验证码
            code = StrUtils.getRandomString(6);
        }
        //5.将验证码和时间存入redis,设置5分钟
        System.out.println(code);
        redisTemplate.opsForValue().set(rediskey,code+":"+date.getTime(),300*1000,TimeUnit.MILLISECONDS);
        //6.将注册信息存入信息表中，打印日志
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle("注册验证码");
        messageSms.setContent("您的验证码为" + code + ", 请在 5 分钟内使用");
        messageSms.setSendTime(date);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getRemoteAddr();
        messageSms.setIp(ip);
        messageSmsService.insert(messageSms);
        //6.打印短信验证码
        log.info("你的验证码:"+code);
    }*/

/*    @Override
    public void smsCode(SmsImgDto smsImgDto) {
        String phone = smsImgDto.getMobile();
        //1.校验手机号是否为空
        AssertUtil.isPhone(phone,GlobalErrorCode.PHONE_ERROR);
        //2.校验图形验证码是否正确
        //3.查询redis是否有手机验证码
        String rediskey = String.format(CommonConstants.Register_PHONE_PREFIX,phone);
        // 保存到redis中
        Object obj = redisTemplate.opsForValue().get(rediskey);
        Date date = new Date();
        String code = "";
        //4.判断手机验证码是否为空
        if (obj!=null){
            //1.用RedisSmsDto接收obj中参数
            RedisSmsDto redisSmsDto = (RedisSmsDto)obj;

            //2.在判断时间是否大于1分钟
            Boolean boo1 = (date.getTime() - redisSmsDto.getTime())< smsCodeConstants.getInterval();
            //小于1分钟，返回提示
            AssertUtil.isFalse(boo1,GlobalErrorCode.OPERATING_FREQUENTLY_ERROR);
            //大于一分钟，将之前的验证码重新发
            String code1 = redisSmsDto.getCode();
        }else{ // 如果不存在创建一个验证码
            code = StrUtils.getRandomString(smsCodeConstants.getCodesize());
        }
        //5.存入redis中
        RedisSmsDto redisSmsDto = new RedisSmsDto(code,date.getTime());
        redisTemplate.opsForValue().set(rediskey,redisSmsDto,smsCodeConstants.getTimeout(),TimeUnit.MILLISECONDS);
        sendMessageSms(date, code);
    }

    private void sendMessageSms(Date date, String code) {
        //6.将注册信息存入信息表中，打印日志
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(smsCodeConstants.getSmstitle());
        String conut = String.format(smsCodeConstants.getSmsmessage(), code);
        messageSms.setContent(conut);
        messageSms.setSendTime(date);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getRemoteAddr();
        messageSms.setIp(ip);
        messageSmsService.insert(messageSms);
        //6.打印短信验证码
        log.info(conut);
    }*/
}
